package middle;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class Solution_71 {

    public static void main(String[] args) {
        Solution_71 model = new Solution_71();
        System.out.println(model.simplifyPath("/home/"));
        System.out.println(model.simplifyPath("/../"));
        System.out.println(model.simplifyPath("/home//foo/"));
        System.out.println(model.simplifyPath("/a/./b/../../c/"));
        System.out.println(model.simplifyPath("/..hidden"));
    }

    public String simplifyPath(String path) {
        path += "/";
        Status status = Status.SLASH;
        StringBuilder builder = new StringBuilder();
        Stack<String> stack = new Stack<>();
        for (int i = 0; i < path.length(); i++) {
            char c = path.charAt(i);
            CharacterType characterType = transfer(c);
            switch (status) {
                case SLASH:
                    switch (characterType) {
                        case Character_SLASH:
                            break;
                        case Character_POINT:
                        case Character_ALPHA:
                            builder.append(c);
                            break;
                        default:
                    }
                    break;
                case POINT:
                    switch (characterType) {
                        case Character_SLASH:
                            builder.delete(0, builder.length());
                            break;
                        case Character_ALPHA:
                        case Character_POINT:
                            builder.append(c);
                        default:
                    }
                    break;
                case TWO_POINT:
                    switch (characterType) {
                        case Character_SLASH:
                            if (!stack.empty()) {
                                stack.pop();
                            }
                            builder.delete(0, builder.length());
                            break;
                        case Character_ALPHA:
                        case Character_POINT:
                            builder.append(c);
                        default:
                    }
                    break;
                case THREE_POINT:
                case ALPHA:
                    switch (characterType) {
                        case Character_SLASH:
                            stack.push(builder.toString());
                            builder.delete(0, builder.length());
                            break;
                        case Character_ALPHA:
                        case Character_POINT:
                            builder.append(c);
                        default:
                    }
                    break;
                case POINT_SLASH:
                    builder.delete(0, builder.length());
                    switch (characterType) {
                        case Character_SLASH:
                            break;
                        case Character_ALPHA:
                        case Character_POINT:
                            builder.append(c);
                            break;
                        default:
                    }
                    break;
                case TWO_POINT_SLASH:
                    switch (characterType) {
                        case Character_SLASH:
                            break;
                        case Character_ALPHA:
                        case Character_POINT:
                            builder.append(c);
                            break;
                        default:
                    }
                    break;
                default:
            }
            status = map.get(status).get(characterType);
        }
        if (stack.empty()) {
            return "/";
        }
        builder.delete(0, builder.length());
        while (!stack.empty()) {
            builder.insert(0, stack.pop()).insert(0, '/');
        }
        return builder.toString();
    }

    private CharacterType transfer(Character c) {
        if (c == '.') {
            return CharacterType.Character_POINT;
        } else if (c == '/') {
            return CharacterType.Character_SLASH;
        }
        return CharacterType.Character_ALPHA;
    }

    enum Status {
        SLASH, POINT, TWO_POINT, THREE_POINT, ALPHA, POINT_SLASH, TWO_POINT_SLASH
    }

    enum CharacterType {
        Character_SLASH, Character_POINT, Character_ALPHA
    }

    private static Map<Status, Map<CharacterType, Status>> map = new HashMap<>();
    static {
        Map<CharacterType, Status> tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_SLASH, Status.SLASH);
        tempMap.put(CharacterType.Character_POINT, Status.POINT);
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        map.put(Status.SLASH, tempMap);

        tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_SLASH, Status.POINT_SLASH);
        tempMap.put(CharacterType.Character_POINT, Status.TWO_POINT);
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        map.put(Status.POINT, tempMap);

        tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_SLASH, Status.TWO_POINT_SLASH);
        tempMap.put(CharacterType.Character_POINT, Status.THREE_POINT);
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        map.put(Status.TWO_POINT, tempMap);

        tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_SLASH, Status.SLASH);
        tempMap.put(CharacterType.Character_POINT, Status.THREE_POINT);
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        map.put(Status.THREE_POINT, tempMap);

        tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        tempMap.put(CharacterType.Character_SLASH, Status.SLASH);
        tempMap.put(CharacterType.Character_POINT, Status.ALPHA);
        map.put(Status.ALPHA, tempMap);

        tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_POINT, Status.POINT);
        tempMap.put(CharacterType.Character_SLASH, Status.SLASH);
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        map.put(Status.POINT_SLASH, tempMap);

        tempMap = new HashMap<>();
        tempMap.put(CharacterType.Character_POINT, Status.POINT);
        tempMap.put(CharacterType.Character_SLASH, Status.SLASH);
        tempMap.put(CharacterType.Character_ALPHA, Status.ALPHA);
        map.put(Status.TWO_POINT_SLASH, tempMap);
    }
}
